#pragma once
#define _CRT_SECURE_NO_WARNINGS

#include <cassert>
#include <string>
#include <vector>
#include <exception>
#include "Location.hpp"

#define WelpErrorIf(condition, message) assert(!(condition))
#define WelpError(message) assert(false)

#ifndef _MSC_VER
  #define override
#endif

namespace Welp
{
  using namespace std;

  string Format(const char* format, ...);

  namespace ExceptionType
  {
    enum Enum
    {
      Internal,
      Tokenizer,
      Parser,
      Runtime
    };
  }

  class Exception
  {
  public:
    string mMessage;
    string mConsoleMessage;
    Location mLocation;
    ExceptionType::Enum mType;

    Exception(const string& message, ExceptionType::Enum type, const Location* location);
    virtual ~Exception();
    void Print();
  };

  template <typename T>
  T& push_and_create(vector<T>& array)
  {
    array.resize(array.size() + 1);
    return array.back();
  }

  class GraphVisualizer
  {
  public:
    
    string mText;

    void BeginDiGraph(const char* name = "mygraph");
    void EndGraph();

    void AddNode(const char* name, const char* label = "", const char* shape = "box", const char* color = "black");
    void AddEdge(const char* from, const char* to, const char* label = "", const char* style = "solid", const char* color = "black");

    void Visualize(const char* svgPath = "..\\Output\\output.svg", const char* dotPath = "..\\Output\\output.txt", const char* graphVizPath = "..\\GraphViz\\dot.exe");
  };
}
